﻿#pragma once
#include "AsContainerBasics.h"

AS_MEMBER_CLASS_DECLARATION(AsTextStream);

class AS_BASIC_EXPORT AsTextStream {
public:
	enum Flag {
		None,
		AutoSpace,
	};

public:
	AsTextStream(Flag flag = AutoSpace);
	AsTextStream(const std::string& str, Flag flag = AutoSpace);
	~AsTextStream();
	
private:
	AS_MEMBER_CLASS(AsTextStream)* mp;

public:
	void setFlag(Flag flag);
	void toHead();
	void clear();
	std::string str();

public:
	AsTextStream& linefeed();
	void writeText(const std::string& text);
	void readText(std::string& text);

public:
	AsTextStream& operator<<(bool data);
	AsTextStream& operator<<(char data);
	AsTextStream& operator<<(uchar data);
	AsTextStream& operator<<(short data);
	AsTextStream& operator<<(ushort data);
	AsTextStream& operator<<(int data);
	AsTextStream& operator<<(uint data);
	AsTextStream& operator<<(long data);
	AsTextStream& operator<<(unsigned long data);
	AsTextStream& operator<<(long long data);
	AsTextStream& operator<<(unsigned long long data);
	AsTextStream& operator<<(float data);
	AsTextStream& operator<<(double data);
	AsTextStream& operator<<(long double data);
	AsTextStream& operator<<(const char* data);
	AsTextStream& operator<<(const std::string& data);

	AsTextStream& operator<<(const cv::Point& data);
	AsTextStream& operator<<(const cv::Point2f& data);
	AsTextStream& operator<<(const cv::Point2d& data);
	AsTextStream& operator<<(const cv::Point3f& data);
	AsTextStream& operator<<(const cv::Size& data);
	AsTextStream& operator<<(const cv::Size2f& data);
	AsTextStream& operator<<(const cv::Vec2i& data);
	AsTextStream& operator<<(const cv::Vec3i& data);
	AsTextStream& operator<<(const cv::Vec4i& data);
	AsTextStream& operator<<(const cv::Vec6i& data);
	AsTextStream& operator<<(const cv::Vec2f& data);
	AsTextStream& operator<<(const cv::Vec3f& data);
	AsTextStream& operator<<(const cv::Vec4f& data);
	AsTextStream& operator<<(const cv::Vec6f& data);
	AsTextStream& operator<<(const cv::Vec2d& data);
	AsTextStream& operator<<(const cv::Vec3d& data);
	AsTextStream& operator<<(const cv::Vec4d& data);
	AsTextStream& operator<<(const cv::Vec6d& data);
	AsTextStream& operator<<(const cv::Rect& data);
	AsTextStream& operator<<(const cv::Rect2f& data);
	AsTextStream& operator<<(const cv::RotatedRect& data);

	AsTextStream& operator>>(bool& data);
	AsTextStream& operator>>(char& data);
	AsTextStream& operator>>(uchar& data);
	AsTextStream& operator>>(short& data);
	AsTextStream& operator>>(ushort& data);
	AsTextStream& operator>>(int& data);
	AsTextStream& operator>>(uint& data);
	AsTextStream& operator>>(long& data);
	AsTextStream& operator>>(unsigned long& data);
	AsTextStream& operator>>(long long& data);
	AsTextStream& operator>>(unsigned long long& data);
	AsTextStream& operator>>(float& data);
	AsTextStream& operator>>(double& data);
	AsTextStream& operator>>(long double& data);
	AsTextStream& operator>>(std::string& data);

	AsTextStream& operator>>(cv::Point& data);
	AsTextStream& operator>>(cv::Point2f& data);
	AsTextStream& operator>>(cv::Point2d& data);
	AsTextStream& operator>>(cv::Point3f& data);
	AsTextStream& operator>>(cv::Size& data);
	AsTextStream& operator>>(cv::Size2f& data);
	AsTextStream& operator>>(cv::Vec2i& data);
	AsTextStream& operator>>(cv::Vec3i& data);
	AsTextStream& operator>>(cv::Vec4i& data);
	AsTextStream& operator>>(cv::Vec6i& data);
	AsTextStream& operator>>(cv::Vec2f& data);
	AsTextStream& operator>>(cv::Vec3f& data);
	AsTextStream& operator>>(cv::Vec4f& data);
	AsTextStream& operator>>(cv::Vec6f& data);
	AsTextStream& operator>>(cv::Vec2d& data);
	AsTextStream& operator>>(cv::Vec3d& data);
	AsTextStream& operator>>(cv::Vec4d& data);
	AsTextStream& operator>>(cv::Vec6d& data);
	AsTextStream& operator>>(cv::Rect& data);
	AsTextStream& operator>>(cv::Rect2f& data);
	AsTextStream& operator>>(cv::RotatedRect& data);

	template <typename _Type>
	AsTextStream& operator<<(const _Type& data) {
		*this << "Unknown";
		return *this;
	}
	template <typename _Type>
	AsTextStream& operator>>(_Type& data) {
		std::string tmp;
		*this >> tmp;
		return *this;
	}

	template <typename _Type>
	AsTextStream& operator<<(const std::vector<_Type>& datas) {
		*this << '[' << datas.size() << ']';
		linefeed();
		for (const auto& data : datas) {
			*this << data;
			linefeed();
		}
		return *this;
	}
	template <typename _Type>
	AsTextStream& operator>>(std::vector<_Type>& datas) {
		char tmp;
		size_t size = 0;
		*this >> tmp >> size >> tmp;
		datas.resize(size);
		for (auto& data : datas) {
			*this >> data;
		}
		return *this;
	}

};

